package org.ielse.frame;

import java.util.Map;
import java.util.Set;

import org.ielse.frame.t.volley.GsonRequest;
import org.ielse.frame.util.BaseUtil;
import org.ielse.frame.util.NetworkUtil;
import org.ielse.frame.view.ShinyLayout;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;

public class BaseActivity extends Activity {

	protected SharedPreferences spfs;
	protected RequestQueue requestQueue;

	@Override protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		logd("onCreate()");
		spfs = App.i().getSharedPreferences();
		requestQueue = App.i().getRequestQueue();
	}

	@Override protected void onResume() {
		super.onResume();
		logd("onResume()");
	}

	@Override protected void onDestroy() {
		super.onDestroy();
		logd("onDestroy()");
	}

	@Override public void setContentView(int layoutResID) {
		setContentView(inflater(layoutResID));
	}

	@Override public void setContentView(View view) {
		setContentView(view, null);
	}

	@Override public void setContentView(View view, ViewGroup.LayoutParams params) {

		ShinyLayout contentWrapper = new ShinyLayout(this);
		contentWrapper.setOnTouchListener(new View.OnTouchListener() {
			@Override public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_CANCEL:
				case MotionEvent.ACTION_UP:
					hideSoftInputFromWindow();
					break;
				}
				return false;

			}
		});
		contentWrapper.addView(view, 0);

		if (params != null) {
			super.setContentView(contentWrapper, params);
		} else {
			super.setContentView(contentWrapper);
		}
	}

	@Override public void startActivity(Intent intent) {
		super.startActivity(intent);
		overridePendingTransition(R.anim.slide_right_enter, R.anim.slide_left_exit);
	}

	@Override public void finish() {
		super.finish();
		if (ActivityCollector.size() > 1) {
			overridePendingTransition(R.anim.slide_left_enter, R.anim.slide_right_exit);
		}
	}

	public void hideSoftInputFromWindow() {
		if (this.getCurrentFocus() != null) {
			((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(this.getCurrentFocus()
					.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
		}
	}

	public void showToast(int resId) {
		showToast(getString(resId));
	}

	public void showToast(String text) {
		Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
	}

	public void startActivity(Class<?> targetActivity, Object... params) {
		startActivity(targetActivity, BaseUtil.initBundle(params));
	}

	public void startActivity(Class<?> targetActivity, Bundle bundle) {
		Intent intent = new Intent(this, targetActivity);
		if (bundle != null) {
			intent.putExtras(bundle);
		}
		startActivity(intent);
	}

	public void logi(String text) {
		if (C.settings.DEBUG && !TextUtils.isEmpty(text))
			Log.i(getClass().getSimpleName(), text);
	}

	public void logd(String text) {
		if (C.settings.DEBUG && !TextUtils.isEmpty(text))
			Log.d(getClass().getSimpleName(), text);
	}

	public void logw(String text) {
		if (C.settings.DEBUG && !TextUtils.isEmpty(text))
			Log.w(getClass().getSimpleName(), text);
	}

	public void loge(String text) {
		if (C.settings.DEBUG && !TextUtils.isEmpty(text))
			Log.e(getClass().getSimpleName(), text);
	}

	public void writeToSpfs(String key, Object value) {
		Editor editor = spfs.edit();
		if (value instanceof String) {
			editor.putString(key, (String) value);
		} else if (value instanceof Integer) {
			editor.putInt(key, (Integer) value);
		} else if (value instanceof Boolean) {
			editor.putBoolean(key, (Boolean) value);
		} else if (value instanceof Float) {
			editor.putFloat(key, (Float) value);
		} else if (value instanceof Long) {
			editor.putLong(key, (Long) value);
		} else {
			throw new IllegalArgumentException("not support type");
		}
		editor.commit();
	}

	public String readStringFromSpfs(String key) {
		return readStringFromSpfs(key, null);
	}

	public String readStringFromSpfs(String key, String defValue) {
		return spfs.getString(key, defValue);
	}

	public int readIntFromSpfs(String key) {
		return readIntFromSpfs(key, 0);
	}

	public int readIntFromSpfs(String key, int defValue) {
		return spfs.getInt(key, defValue);
	}

	public float readFloatFromSpfs(String key) {
		return readFloatFromSpfs(key, 0f);
	}

	public float readFloatFromSpfs(String key, float defValue) {
		return spfs.getFloat(key, defValue);
	}

	public boolean readBooleanFromSpfs(String key) {
		return readBooleanFromSpfs(key, false);
	}

	public boolean readBooleanFromSpfs(String key, boolean defValue) {
		return spfs.getBoolean(key, defValue);
	}

	public long readLongFromSpfs(String key) {
		return readLongFromSpfs(key, 0l);
	}

	public long readLongFromSpfs(String key, long defValue) {
		return spfs.getLong(key, defValue);
	}

	public Set<String> readStringSetFromSpfs(String key) {
		return readStringSetFromSpfs(key, null);
	}

	public Set<String> readStringSetFromSpfs(String key, Set<String> defValues) {
		return spfs.getStringSet(key, defValues);
	}

	public boolean containsFromSpfs(String key) {
		return spfs.contains(key);
	}

	public boolean removeSpfs(String key) {
		return spfs.edit().remove(key).commit();
	}

	public boolean clearSpfs() {
		return spfs.edit().clear().commit();
	}

	public <T> void post(final String url, final Map<String, String> params, final Class<T> clazz, final VolleyListener<T> listener) {
		request(Method.POST, url, params, clazz, listener);
	}

	public <T> void get(final String url, final Map<String, String> params, final Class<T> clazz, final VolleyListener<T> listener) {
		request(Method.GET, url, params, clazz, listener);
	}

	private <T> void request(int method, final String url, final Map<String, String> params, final Class<T> clazz,
			final VolleyListener<T> listener) {
		GsonRequest<T> gsonRequest = new GsonRequest<T>(Method.GET, url, clazz, new Response.Listener<T>() {
			@Override public void onResponse(T response) {
				logd("onResponse(): " + url + "\nresponse:" + response);
				if (listener != null)
					listener.onResponse(response);
			}
		}, new Response.ErrorListener() {
			@Override public void onErrorResponse(VolleyError error) {
				logd("onErrorResponse(): " + url + "\nerror:" + error.getMessage());
				if (listener != null)
					listener.onErrorResponse(error);
			}
		}) {
			@Override protected Map<String, String> getParams() throws AuthFailureError {
				return params;
			}
		};

		logd("request()\nurl:" + url + "\nparams:" + params);

		requestQueue.add(gsonRequest);
	}

	public class VolleyListener<T> implements Response.Listener<T>, Response.ErrorListener {
		@Override public void onResponse(T response) {
		}

		@Override public void onErrorResponse(VolleyError error) {
			showToast(NetworkUtil.isNoInternet() ? R.string.error_net : R.string.error_request);
		}
	}

	public View inflater(int resource) {
		return LayoutInflater.from(this).inflate(resource, null);
	}

	public void startService(Class<?> service) {
		Intent intent = new Intent(this, service);
		startService(intent);
	}

	public void stopService(Class<?> service) {
		Intent intent = new Intent(this, service);
		stopService(intent);
	}

	public void bindService(Class<?> service, ServiceConnection conn) {
		Intent intent = new Intent(this, service);
		bindService(intent, conn, BIND_AUTO_CREATE);
	}

	public void registerReceiver(BroadcastReceiver receiver, String... actions) {
		IntentFilter filter = new IntentFilter();
		for (String act : actions) {
			filter.addAction(act);
		}
		registerReceiver(receiver, filter);
	}
}
